package com.ctsi.commons.event;

import com.ctsi.commons.event.config.Event;
import com.ctsi.commons.event.config.EventConfigReader;
import com.ctsi.commons.event.config.EventModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 事件发布入口，应该通过spring保证唯一性
 * 
 * @author zhangjw
 * 
 */
@Component
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public class EventPublisherMan {
	private static final Logger log = LoggerFactory.getLogger(EventPublisherMan.class);

	private final Observable ep;
	private final List<EventModule> mList = new CopyOnWriteArrayList<EventModule>();
	private volatile boolean initialized = false;

	// AtomicBoolean initialized1;
	public EventPublisherMan() {
		ep = new Observable();

	}

	private static final EventPublisherMan eventPublisherMan = new EventPublisherMan();

	public static final EventPublisherMan getEventPublisherMan() {
		return eventPublisherMan;
	}

	private synchronized void initialize() {

		// 初始化
		if (!initialized) {
			mList.addAll(EventConfigReader.readEventConfig());
			for (EventModule em : mList) {
				List<Event> eList = em.getEventList();

				ep.addEventDefine(eList, true);

			}
			initialized = true;
		}

	}

	private void ini() {
		if (!initialized) {
			log.debug("initialize");
			initialize();
		}
	}

	public EventPublisher getEventPublisher() {
		ini();
		return ep;
	}

	/**
	 * 禁止模块,但是没有删除内存中的事件定义
	 * 
	 * @param moduleId
	 */
	public void disableModule(String moduleId) {
		ini();
		EventModule em = getEventModuleById(mList, moduleId);
		if (em == null) {
			log.warn("{} not found", moduleId);
			return;
		}

		List<Event> eList = em.getEventList();
		for (Event e : eList) {
			ep.disableEvent(e.getEventid(), e.getId());
		}
		log.info("disable:{}", moduleId);
	}

	/**
	 * 读入被禁止的模块 注意,没有增加
	 * 
	 * @param moduleId
	 */
	public void enableModule(String moduleId) {
		ini();
		List<EventModule> mListNoCheck = EventConfigReader.readEventConfigNoCheck();
		EventModule em = getEventModuleById(mListNoCheck, moduleId);
		if (em == null || em.isEnable()) {
			log.warn("{} not found ,or already enable ", moduleId);
			return;
		}

		List<Event> eList = em.getEventList();

		ep.addEventDefine(eList, false);

		log.info("enable:{}", moduleId);
	}

	/**
	 * 禁止一个监听,但是如果已经初始化,则无效
	 * 
	 * @param event 监听器的监听的id
	 */
	public void disableOneObserver(Event event) {
		ini();
		log.info("disable event : {}", event.getName());
		((Observable) ep).disableEvent(event.getEventid(), event.getId());
	}

	public List<Observer> getObservers(String sourceId) {
		ini();
		return ((Observable) ep).getObservers(sourceId);
	}

	public EventModule getEventModuleById(List<EventModule> mListF, String moduleId) {
		for (EventModule em : mListF) {
			if (em.getModuleId().equals(moduleId)) {
				return em;
			}
		}
		return null;
	}

	public EventModule getEventModuleById(String moduleId) {
		for (EventModule em : mList) {
			if (em.getModuleId().equals(moduleId)) {
				return em;
			}
		}
		return null;
	}

	public List<EventModule> getModuleList() {
		ini();
		return Collections.unmodifiableList(mList);
	}

	/**
	 * 动态注册一个模块
	 * 
	 * @param em
	 * @return
	 */
	public boolean addModuleList(EventModule em) {
		ini();
		if (em != null) {
			if (mList.contains(em)) {
				log.info("already contain :{}", em);
				return false;
			}
			log.info("add  ModuleList:{}", em);
			boolean result = mList.add(em);
			if (result) {
				List<Event> eList = em.getEventList();

				ep.addEventDefine(eList, false);
			}
			return result;
		} else {
			throw new IllegalArgumentException("EventModule is null");
		}

	}

	public boolean registerObserver(String eventId, Observer obs) {
		ini();
		return ep.registeObserver(eventId, obs);
	}

	public boolean unRegisterObserver(String eventId, Observer obs) {
		ini();
		return ((Observable) ep).unRegisteObserver(eventId, obs);
	}

	/**
	 * 指定的id是否本地发布的事件
	 * 
	 * @param eventid
	 * @return
	 */
	public boolean isLocalEvent(String eventid) {
		for (EventModule em : mList) {
			if (em.containEventSource(eventid)) {
				return true;
			}
		}
		return false;
	}

}
